package dashboard.cli;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;

import dashboard.dbentity.UploadDocInfo;

public class MyPdf2swf{
	protected static String OS = System.getProperty("os.name");
	private static String CMD = "pdf2swf";
	private static String CMDParams = " {path.pdf}{pdffile} -o {path.swf}{pdffile}.swf -f -T 9 {params}";
	private static String ppt2PDF_CMD = "/opt/libreoffice4.2/program/soffice --invisible --convert-to pdf --outdir {path.pdf} {path.pdf}{officefile}";
	private static Map<String,String> config = new HashMap<String,String>();
	private static Map<String,Integer> docTypeMap = new HashMap<String,Integer>();
	
    static{
		docTypeMap.put("doc", 1);
		docTypeMap.put("docx", 1);
		docTypeMap.put("ppt", 2);
		docTypeMap.put("pptx", 2);
		docTypeMap.put("pps", 2);
		docTypeMap.put("ppsx", 2);
		docTypeMap.put("xls", 3);
		docTypeMap.put("xlsx", 3);
		docTypeMap.put("pdf", 4);
		docTypeMap.put("application/msword", 1);
		docTypeMap.put("application/vnd.ms-powerpoint", 2);
		docTypeMap.put("application/vnd.ms-excel", 3);
		docTypeMap.put("application/pdf", 4);
	}
    
	static{
		if(isWin()){
			CMD = "D:\\Program Files\\SWFTools\\pdf2swf.exe";
			ppt2PDF_CMD="D:/libreOffice4/program/soffice --invisible --convert-to pdf --outdir \"{path.pdf}\" \"{path.pdf}{officefile}\"";
		}
		config.put("CMD", CMD);
		config.put("CMDParams", CMDParams);
		config.put("ppt2PDF_CMD", ppt2PDF_CMD);
	}
	
	private String userName ="";
	private List<UploadDocInfo> toDealList = new ArrayList<UploadDocInfo>();
	private StringBuffer errorMsg = new StringBuffer();
	
	public MyPdf2swf(UploadDocInfo docInfo) {
		String userName = docInfo.getFileCreater();
		if(!StringUtils.isBlank(userName)){
			this.userName += userName+"@58.com";
		}
		if("zip".equals(docInfo.getFileType())){
			toDealList = unZipWithRandomName(docInfo);
		}else{
			toDealList.add(docInfo);
		}
	}
	
	public static boolean accepeType(String type ){
		return docTypeMap.containsKey(type);
	}
	public static boolean isWin(){
		if(OS.contains("Win"))
			return true;
		return false;
	}

	public static String get(String paramName){
		return config.get(paramName);
	}
	
	/**使用的是org.apache.tools.zip包下面的相关类解压缩
	 * jdk自带的zip包对中文文件名支持不友好
	 * @return  
	 */
	public List<UploadDocInfo> unZipWithRandomName(UploadDocInfo docInfo) {
		List<UploadDocInfo>  docList = new ArrayList<UploadDocInfo>();
		String destdir = ".";
		
		try {
			//zip文件
			File file = new File(destdir+docInfo.getSaveName());
			if(!file.exists()){
				return docList;
			}
			ZipFile zipFile = new ZipFile(file,"GB2312");  
			@SuppressWarnings("unchecked")
			Enumeration<ZipEntry> e = zipFile.getEntries(); 
			 while(e.hasMoreElements()) {   
		        ZipEntry zipEntry = (ZipEntry)e.nextElement(); 
				if (zipEntry.isDirectory()) {
					continue;
				}
				//每个条目构造一个DocInfo
				UploadDocInfo docEntry = new UploadDocInfo();
				String srcName = zipEntry.getName();
				if(srcName.indexOf("/") >= 0){ //去掉名称中的目录部分
					srcName = srcName.substring(srcName.lastIndexOf("/")+1);
				}
				String suffix = "";	//文件名后缀
				if(srcName.indexOf(".") >= 0)
					suffix = srcName.substring(srcName.lastIndexOf(".")+1);
//				 System.err.println(zipEntry.getName()+" : "+suffix+" : "+UploadPDFController.getMimeType(suffix));
				//随机名
				String saveName = (int)(Math.random()*100000)+System.currentTimeMillis()+(int)(Math.random()*100000)+"."+suffix;
				
				FileOutputStream fout = new FileOutputStream(destdir + saveName); // 得到目标文件流
				int size = 0;
				byte[] buf = new byte[1024];
				InputStream zin = zipFile.getInputStream(zipEntry);
				while ((size = zin.read(buf)) != -1) { // 每个entry都有一个文件末尾的标识
					fout.write(buf, 0, size);
				}
				docEntry.setUploadTime(docInfo.getUploadTime());
				docEntry.setInitalFileName(srcName);
				docEntry.setSaveName(saveName);
				docEntry.setFileCate1(docInfo.getFileCate1());
				docEntry.setFileCate2(docInfo.getFileCate2());
				docEntry.setFileDescribe(docInfo.getFileDescribe());
				docEntry.setFileCreater(docInfo.getFileCreater());
				docEntry.setFileSize(zipEntry.getSize());
				docEntry.setState(1);
				
				docList.add(docEntry);
				zin.close();
				fout.close();
			}
			 	ZipFile.closeQuietly(zipFile);
			 	file.delete();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return docList;
	}
	
	
	/**
	 * 命令解析
	 * @param commandLine
	 * @return
	 */
	public static ArrayList<String> commandLineAsList(String commandLine) {
		ArrayList<String> commands = new ArrayList<String>();
		String elt = "";
		boolean insideString = false;

		for (int i = 0; i < commandLine.length(); i++) {
			char c = commandLine.charAt(i);

			if (!insideString && (c == ' ' || c == '\t')) {
				if (elt.length() > 0) {
					commands.add(elt);
					elt = "";
				}
				continue;
			} else if (c == '"') {
				insideString = !insideString;
			}

			elt += c;
		}
		if (elt.length() > 0) {
			commands.add(elt);
		}

		return commands;
	}
	
	/**
	 * 命令执行方式一
	 * @param execString
	 * @return
	 * @throws Exception
	 */
	public static boolean execs(String execString) throws Exception {
		
		ArrayList<String> commands = commandLineAsList(execString);
		System.out.println(commands);
		ProcessBuilder pb = new ProcessBuilder(commands);
		pb.redirectErrorStream(true);
		Process p = pb.start();
		BufferedReader is = new BufferedReader(new InputStreamReader(
				p.getInputStream()));
		String line;
		while ((line = is.readLine()) != null) {
			String ret = line;
			System.err.println(ret);
		}
		if (p.waitFor() != 0) {
			System.err.println("命令执行失败! "+p.exitValue());// p.exitValue()==0表示正常结束，1：非正常结束
			throw new IllegalThreadStateException("ERROR: "+execString);
		}
		return true;
	}
	
	/**
	 * 命令执行方式二
	 * @param cmd
	 * @return
	 * @throws IOException
	 */
	public static boolean execute(String cmd) throws IOException{
		Runtime runtime = Runtime.getRuntime();
		Process process = runtime.exec(cmd);
		try {
			System.out.println("----start execute----");
			System.out.println(cmd);
			StreamRedirect stdout=new StreamRedirect(process.getInputStream(),System.out); // 启动单独的线程来清空process.getInputStream()的缓冲区
			StreamRedirect stderr=new StreamRedirect(process.getErrorStream(),System.err);
			stdout.start();
			stderr.start();
			if (process.waitFor() != 0) {
				System.out.println("命令执行失败! "+process.exitValue());// p.exitValue()==0表示正常结束，1：非正常结束
				return false;
			}
			System.out.println("-------finished------");
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	/**
	 * pdf转swf
	 * @param pdfFilename
	 * @return
	 * @throws Exception 
	 */
	public static boolean pdf2swf(String pdfFilename) throws Exception{
		String fullName = config.get("path.pdf")+pdfFilename;
		File file = new File(fullName);
		long size = file.length()/1024;	//文件大小, k
		String params = "-s storeallcharacters";
		if(size > 1024*10){	//文件大于10M,将图形转换为点阵，否则可能会报错： SWF only supports 65536 shapes at once
			params = "-G -s poly2bitmap";
		}
		String cmd = config.get("CMD") + config.get("CMDParams");
		cmd = cmd.replace("{path.pdf}", config.get("path.pdf"));
		cmd = cmd.replace("{path.swf}", config.get("path.swf"));
		cmd = cmd.replace("{pdffile}", pdfFilename);
		cmd = cmd.replace("{params}", params);
		execs(cmd);
		return true;
	}
	
	/**
	 * 使用libreOffice将office文档转换为pdf
	 * 对含有图片的word文档转换效果较差
	 * @param officeFileName
	 * @return
	 * @throws Exception
	 */
	public static boolean office2pdf(String officeFileName) throws Exception{
		
			String cmd = config.get("ppt2PDF_CMD");
			cmd = cmd.replace("{path.pdf}", config.get("path.pdf"));
			cmd = cmd.replace("{officefile}", officeFileName);
			execs(cmd);
			return true;
	}
	
	
	static class StreamRedirect implements Runnable {
		private InputStream is;
		private OutputStream os;
		private Thread thread;

		public StreamRedirect(InputStream is, OutputStream os) {
			this.is = is;
			this.os = os;
		}

		public void start() {
			thread = new Thread(this);
			thread.setDaemon(true);
			thread.start();
		}

		public void run() {
			try {
				BufferedReader br = new BufferedReader(
						new InputStreamReader(is));
				PrintStream printer=new PrintStream(os);
				String line;
				while ((line = br.readLine()) != null)
						printer.println(line);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		public void join() throws InterruptedException {
			thread.join();
		}
	}
	
	/**
	 * 文档转换方法，统一入口
	 * @param fileName
	 * @param mimiType
	 * @return
	 * @throws Exception 
	 */
	public  boolean trans2swf(String fileName,String mimiType){
		try {
			boolean office2pdf_result = false;
			String prefixName = fileName;
			int dotLocation = fileName.lastIndexOf(".");
			if (dotLocation > 0) {
//				String suffix  = prefixName.substring(dotLocation + 1);
				prefixName = prefixName.substring(0, dotLocation);
			}
			int type = docTypeMap.get(mimiType);
			switch (type) {
			case 2:
			case 3: // ppt,excel
				office2pdf_result = office2pdf(fileName);
				break;
			case 4: // pdf
				office2pdf_result = true;
				break;
			default:
				return false;
			}
			if (office2pdf_result && pdf2swf(prefixName + ".pdf"))
				return true;
		} catch (Exception e) {
			errorMsg.append(fileName + ":<br>" + e.getMessage() + "<br>");
			e.printStackTrace();
		}
		return false;
	}
	
	public static void errorWarn(String shortMsg, String longMsg){
		//短信报警
		Map<String,String> sendMap = new HashMap<String, String>();
    	sendMap.put("13522482231",shortMsg);
   	}
	
	public static void main(String[] args) throws Exception{
		String docfile="2014.doc";
		office2pdf(docfile);
		pdf2swf(docfile.substring(0,docfile.lastIndexOf("."))+".pdf");
	}
	
}
